#pragma once

#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/epoll.h>
#include <errno.h>
#include <error.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <sys/socket.h>
#include <unistd.h>
#include <termios.h>
#include <sys/wait.h>
#include <mysql/mysql.h>
#include <dirent.h>
#include <stdarg.h>
#include <time.h>
#include <unistd.h>
#include <crypt.h>
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <stdarg.h>
#include <l8w8jwt/encode.h>
#include <unistd.h>
#include <sys/types.h>


#include "Queue.h"
#include "Loop_time_queue.h"

#define LISTEN_LINK 10
#define POOL_NUM 4
#define EVENT_SIZE 10
#define ARGS_LENGTH 2048


extern FILE* error_stream;
extern FILE* info_stream;
extern FILE* debug_stream;

void hong(const char* grade, const char* fmt, ...);

// 日志宏
#define HONG(grade, fmt, ...)   {                                   \
    time_t timer = time(NULL);                                      \
    struct tm *t = localtime(&timer);                               \
    if (strcmp(grade, "error") == 0){                               \
        fprintf(info_stream, "%d年 %d月 %d日 %d:%d:%d %s: %s: %d: ", \
        t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,   \
        t->tm_min, t->tm_sec, __FILE__, __FUNCTION__, __LINE__);    \
        hong(grade, fmt, __VA_ARGS__);                              \
    }else if(strcmp(grade, "info") == 0 ){                          \
        fprintf(info_stream, "%d年 %d月 %d日 %d:%d:%d %s: %s: %d: ", \
        t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,   \
        t->tm_min, t->tm_sec, __FILE__, __FUNCTION__, __LINE__);    \
        hong(grade, fmt, __VA_ARGS__);                              \
    }else if(strcmp(grade, "debug") == 0 ){                         \
        fprintf(debug_stream, "%d年 %d月 %d日 %d:%d:%d %s: %s: %d: ",\
        t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,   \
        t->tm_min, t->tm_sec, __FILE__, __FUNCTION__, __LINE__);    \
        hong(grade, fmt, __VA_ARGS__);                              \
    }                                                               \
}




#define LOG_MSG(msg) {  \
    time_t timer = time(NULL);  \
    struct tm* t = localtime(&timer);   \
    if(msg == "0")  \
        fprintf(stderr, "%d年 %d月 %d日 %d:%d:%d %s: %s: %d: ", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, __FILE__, __FUNCTION__, __LINE__);  \
    else    \
        fprintf(stderr, "%d年 %d月 %d日 %d:%d:%d %s: %s: %d: %s\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, __FILE__, __FUNCTION__, __LINE__, msg); \
    fflush(stderr); \
}

// 线程池
typedef struct 
{
    Queue_t* q;
    pthread_t thread_pid[POOL_NUM];
    bool alive;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
} pool_t;


// 创建线程池
pool_t* create_pool(void);

// 销毁线程池
int destory_pool(pool_t* pool);

// tcp 连接
int tcp(int* fd);

// 增加新连接
int new_link(int current_fd, int epoll_fd, int fd, time_queue_t* time_queue, time_hash_t* hash);

// 增加 epoll 监听
int epoll_add(int epoll_fd, int fd);

// 移除 epoll 监听
int epoll_del(int epoll_fd, int fd);


// 获得配置信息
int getparameter(const char *key, char *value);

// 子线程的入口函数
void* start_routine(void* arg);

// 子线程处理任务的函数
int work(node_t* node, MYSQL* mysql);

// 信号注册函数
void handler(int signum);


// 主线程等待子线程有序退出
int __exit__(pool_t* pool);


// 分析用户发来的信息
int analyse(int sock_fd, int epoll_fd, pool_t* pool, MYSQL* mysql, time_queue_t* time_queue, time_hash_t* hash);

// 登录
int to_login(messenger_t* msg, int sock_fd, MYSQL* mysql);

// 注册
int to_register_(messenger_t* msg, int sock_fd, MYSQL* mysql);

// 验证账户信息
int verify_log(const char* usr, const char* passwd, MYSQL* mysql);
int verify_reg(const char* usr, const char* passwd, MYSQL* mysql);


// ls
int to_ls(messenger_t* msg, int sock_fd, MYSQL* mysql);

// up
int to_up(messenger_t* msg, int sock_fd, MYSQL* mysql);

// mkdir
int to_mkdir(messenger_t* msg, int sock_fd, MYSQL* mysql);

// cd
int to_cd(messenger_t* msg, int sock_fd, MYSQL* mysql);

// cd
int to_rm(messenger_t* msg, int sock_fd, MYSQL* mysql);

// 初始化mysql，并建立连接
int MysqlInit(MYSQL* mysql);

// 得到用户的 id
int usr_id(MYSQL* mysql, const char* usr);

// 得到 token 
int l8w8jwt(char* jwt, size_t* jwt_lenth, int uid);

// 得到 uid
int l8w8jwt_uid(const char* jwt, int* uid);

bool is_have_dir(MYSQL* mysql, const char* dir_path, int uid);


#define ARGS_CHECK(argc, n){                                        \
    if(argc != n){                                                  \
        time_t timer = time(NULL);                                  \
        struct tm *t = localtime(&timer);                           \
        fprintf(stderr, "%d年 %d月 %d日 %d:%d:%d %s: %s: %d: ",      \
        t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,   \
        t->tm_min, t->tm_sec, __FILE__, __FUNCTION__, __LINE__);    \
        fprintf(stderr, "ERROR: expected %d arguments.\n", n);      \
        fflush(stderr);                                             \
    }                                                               \
}

#define ERROR_CHECK(retval, val, msg){                              \
    if(retval == val){                                              \
        time_t timer = time(NULL);                                  \
        struct tm *t = localtime(&timer);                           \
        fprintf(stderr, "%d年 %d月 %d日 %d:%d:%d %s: %s: %d: ",      \
        t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,   \
        t->tm_min, t->tm_sec, __FILE__, __FUNCTION__, __LINE__);    \
        perror(msg);                                                \
        fflush(stderr);                                             \
    }                                                               \
}

#define THREAD_ERROR_CHECK(ret, msg){                               \
    if(ret != 0){                                                   \
        time_t timer = time(NULL);                                  \
        struct tm *t = localtime(&timer);                           \
        fprintf(stderr, "%d年 %d月 %d日 %d:%d:%d %s: %s: %d: ",      \
        t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour,   \
        t->tm_min, t->tm_sec, __FILE__, __FUNCTION__, __LINE__);    \
        fflush(stderr);                                             \
    }                                                               \
}
